package com.dbflow5.adapter.saveable;

import com.dbflow5.adapter.ModelAdapter;
import com.dbflow5.database.DatabaseStatement;
import com.dbflow5.database.DatabaseWrapper;

import java.util.Collection;
import java.util.Iterator;
import java.util.function.BiFunction;

public class ListModelSaver<T> {

    ModelSaver<T> modelSaver;

    ModelAdapter<T> modelAdapter;

    public ListModelSaver(ModelSaver<T> modelSaver){
        this.modelSaver = modelSaver;
        modelAdapter = modelSaver.modelAdapter;
    }


    public synchronized long saveAll(Collection<T> tableCollection, DatabaseWrapper wrapper) {
        return applyAndCount(tableCollection, modelAdapter.getSaveStatement(wrapper), (model, statement) -> modelSaver.save(model, statement, wrapper));
    }

    public synchronized long insertAll(Collection<T> tableCollection, DatabaseWrapper wrapper) {
        return applyAndCount(tableCollection, modelAdapter.getInsertStatement(wrapper), (model, statement) -> modelSaver.insert(model, statement, wrapper) > ModelSaver.INSERT_FAILED);
    }

    public synchronized long updateAll(Collection<T> tableCollection, DatabaseWrapper wrapper) {
        return applyAndCount(tableCollection, modelAdapter.getUpdateStatement(wrapper), (model, statement) -> modelSaver.update(model, statement, wrapper));
    }

    public synchronized long deleteAll(Collection<T> tableCollection, DatabaseWrapper wrapper) {
        return applyAndCount(tableCollection, modelAdapter.getDeleteStatement(wrapper), (model, statement) -> modelSaver.delete(model, statement, wrapper));
    }

    private long applyAndCount(Collection<T> tableCollection, DatabaseStatement databaseStatement, BiFunction<T, DatabaseStatement, Boolean> fn) {
        // skip if empty.
        if (tableCollection.isEmpty()) {
            return 0L;
        }

        long count = 0L;
        for (T t : tableCollection) {
            if (fn.apply(t, databaseStatement)) {
                count++;
            }
        }

        return count;
    }
}
